using System;
using System.Collections.Generic;
using System.Text;

namespace COME342.CollisionResolution.BinaryTree
{
    /// <summary>
    /// Last Insertion Standart Colesced Hashing
    /// Kerem KAT.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class LISCH<T> where T : ILischDataRow
    {
        LischTable<T> hashTable;
        int mod;

        public LISCH(int mod)
        {
            this.mod = mod;
            hashTable = new LischTable<T>(mod);
        }

        public int Insert(T data)
        {
            return hashTable.InsertAt(data.GetId() % mod, data);
        }

        public void Insert(T[] data)
        {
            foreach (T t in data)
                hashTable.InsertAt(t.GetId() % mod, t);
        }

        public int CountProbes(T record)
        {
            return hashTable.CountProbes(record);
        }

        public double GetAverageProbes()
        {
            double sum = 0.0;
            int i = 0;
            foreach (LischTableEntry<T> t in hashTable)
            {
                if (t == null || t.data == null)
                    continue;

                sum += CountProbes(t.data);
                i++;
            }

            if (i == 0)
                return 0;

            return sum / i;
        }

        public double GetPackingFactor()
        {
            int empty = 0;
            int full = 0;
            foreach (LischTableEntry<T> t in hashTable)
            {
                if (t.data == null)
                    empty++;
                else
                    full++;
            }
            return 1.0 * full / (full + empty);
        }

        public int GetRecordCount()
        {
            int full = 0;
            foreach (LischTableEntry<T> t in hashTable)
            {
                if (t.data != null)
                    full++;
            }
            return full;
        }

        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();

            for (int i = 0; i < mod; ++i)
            {
                sb.Append(i);
                sb.Append(": ");
                if (hashTable[i] == null || hashTable[i].data == null)
                    sb.AppendLine("-1\t-1\t-1");
                else
                {
                    sb.Append(hashTable[i].data.GetId());
                    sb.Append("\t");
                    sb.Append(hashTable[i].link.ToString());
                    sb.Append("\t");
                    sb.AppendLine(hashTable[i].data.ToString());
                }
            }
            return sb.ToString();
        }

        public bool DeleteRecord(T record)
        {
            return hashTable.DeleteRecord(record);
        }

        public void DeleteByPosition(int index)
        {
            hashTable.DeleteByPosition(index % mod);
        }
    }
}
